home *** CD-ROM | disk | FTP | other *** search
- *!*********************************************************************
- *!
- *! Source File: DBFDIR.PRG
- *!
- *! System: DBFDIR - Database directory
- *! Author: John Wright
- *! Copyright (c) 1993-1995 John Wright
- *!
- *! Procedures : Force_main
- *!
- *!*********************************************************************
- * 07/20/93 - Modified DISPSTRU to emulate old DBDIR.COM with added
- * support for FoxPro DBFs.
- * 10/07/93 - Added support for dBase II files.
- * 11/15/93 - Display DBF structure if /S specified.
- * 11/16/93 - Check for FoxPro CDX reference.
- * 02/06/94 - Changed to work with Force 2.4 new features/syntax.
- * 06/30/95 - Better support for dBASE II files including structure list.
- * Some old programs still use dBASE II files!!!
-
- #INCLUDE date.hdr
- #INCLUDE fileio.hdr
- #INCLUDE string.hdr
- #INCLUDE system.hdr
- #INCLUDE io.hdr
-
- #PRAGMA w_func_proc-
-
- *!**********************************************
- *!
- *! Procedure Force_main
- *!
- *!Parameters : Type Method Name
- *! : CHAR(127) REFERENCE cmd_line
- *!
- *!**********************************************
- PROCEDURE Force_main
- PARAMETERS CHAR(127) cmd_line
-
- VARDEF
- CHAR cr_lf
- CHAR cPattern
- CHAR cDbfPath
- CHAR cDbfName
- CHAR cText
- CHAR(1) cVersion
- CHAR(3) cLastUpdate
- CHAR(1) cField
- CHAR(1) cCDXbyte
- * field info
- CHAR(10) fld_name
- CHAR(1) fld_type
- CHAR(1) fld_len
- CHAR(1) fld_dec
- INT nHeader
- INT nFields
- INT nRecSize
- INT nLoop
- INT nSpot
- LONG nRecs
- UINT uHandle
- UINT nError
- LOGICAL lStructure
- ENDDEF
-
- cPattern := cmd_line
- cr_lf := CHR(13)+CHR(10)
-
- cText := "DBFDIR v1.4 - Database Directory "+;
- "(c) 1993-1995 John Wright"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- FB_WRITE(&STD_OUT,cr_lf,2)
-
- IF "/?" $ cPattern
- cText := "Display a DBF directory list or file structures."+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " "+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := "Syntax: DBFDIR [<pattern>] [/S] "+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " "+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " Start Size Contents of DBF header"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " ----- ---- ----------------------"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " 0 1 Database version (see list below)"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " 1 3 Date of last update"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " 4 4 Last record (number of records)"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " 8 2 Offset where data starts"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " 9 2 Record size"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " 11 20 Filler "+;
- "(FoxPro DBFs may contain CDX reference)"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " "+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " DEC File type HEX"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " --- --------------------- ---"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " 02 dBASE II 02"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " Valid: 03 dBASE III/Clipper/Fox 03"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " DBF 04 dBASE IV 04"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " ver. 131 dBASE III with Memos 83"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " 139 dBASE IV with Memos 8B"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := " 245 FoxPro with Memos F5"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- QUIT
- ENDIF
-
- cPattern := UPPER(LTRIM(RTRIM(cPattern))) + " "
-
- IF "/S" $ cPattern
- lStructure := .T.
- nLoop := AT( "/S", cPattern )
- cText := SUBSTR( cPattern, 1, nLoop-1 )
- cText += SUBSTR( cPattern, nLoop+2, LEN(cPattern)-2 )
- cPattern := LTRIM(cText)
- ELSE
- lStructure := .F.
- ENDIF
-
- IF cPattern := " "
- cPattern := "*.DBF"
- ENDIF
-
- * Save path if specified (FIND_FSTR only returns the file name)
- DO CASE
- CASE "\" $ cPattern
- cDbfPath := UPPER(SUBSTR(cPattern,1,RAT("\",cPattern)))
- CASE ":" $ cPattern
- cDbfPath := UPPER(SUBSTR(cPattern,1,RAT(":",cPattern)))
- OTHERWISE
- cDbfPath := ""
- ENDCASE
-
- * search for matching file(s)
- IF .NOT. FIND_FIRST( cPattern, 0x20 )
- cText := "ERROR: No files found matching => "+cPattern+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- FB_WRITE(&STD_OUT,cr_lf,2)
- QUIT
- ENDIF
-
- IF .NOT. lStructure
- cText := "Database name Records Last Update Filesize "
- cText += "RecLen Fields Memo Ver"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- ENDIF
-
- REPEAT
-
- * Reset counters and flags
- cVersion := " "
- cCDXbyte := " "
- nFields := 0
- nHeader := 0
- nRecSize := 0
- nRecs := 0
-
- cDbfName := cDbfPath+FIND_FSTR()
-
- IF .NOT. FB_OPEN( uHandle, cDbfName, &B_READ )
- cText := "ERROR: Cannot open file => "+cDbfName+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- LOOP
- ELSE
- cText := SUBSTR( FIND_FSTR() + SPACE(12), 1, 12 )
- ENDIF
-
- * Look for CDX reference
- FB_SEEK(uHandle,28,&FB_BEGIN)
- FB_READ(uHandle,cCDXbyte,1)
-
- * Get the database version - first character
- FB_SEEK(uHandle,0,&FB_BEGIN)
- FB_READ(uHandle,cVersion,1)
-
- IF cVersion $ "âï⌡"
-
- * dBase III compatible file
- IF cVersion <> ""
- * Date of last update stored as three digit character string
- FB_SEEK(uHandle,1,&FB_BEGIN)
- FB_READ(uHandle,cLastUpdate,3)
-
- * Number of records stored as four digit binary number
- FB_SEEK( uHandle, 4, &FB_BEGIN )
- FB_READ( uHandle, nRecs, 4 )
-
- * Header size
- FB_SEEK( uHandle, 8, &FB_BEGIN )
- FB_READ( uHandle, nHeader, 2 )
-
- * Header prologue is 33 and fields are 32 each
- nFields := ( nHeader - 33 ) / 32
-
- * Record size
- FB_SEEK( uHandle, 10, &FB_BEGIN )
- FB_READ( uHandle, nRecSize, 2 )
-
- IF lStructure
-
- cText := "Name of database file: "+FIND_FSTR()+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
-
- cText := "Number of records: "+;
- LTRIM(STR( nRecs, 12, 0 )) + cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
-
- cText := "Date of last update: "+;
- RIGHT("00"+LTRIM(STR(ASC(SUBSTR(cLastUpdate,2,1)),2,0)),2)+"/"+;
- RIGHT("00"+LTRIM(STR(ASC(SUBSTR(cLastUpdate,3,1)),2,0)),2)+"/"+;
- STR(ASC(SUBSTR(cLastUpdate,1,1)),2,0) + cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
-
- IF cCDXbyte = ""
- cText := "CDX reference found!" + cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- ENDIF
-
- cText := "Field Field name Type Width Dec"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
-
- * process the DBF header
- fld_name := " "
- FOR nLoop := 1 TO nFields
- nSpot := (nLoop*32)
- FB_SEEK(uHandle,nSpot,&FB_BEGIN)
-
- * get field name and check first character
- FB_READ(uHandle,fld_name,10)
-
- * CHR(13) means end of field definitions
- IF SUBSTR(fld_name,1,1) <> CHR(13)
-
- * Gobble up an extra character ...
- FB_READ(uHandle,fld_type,1)
-
- * field type - 11th position
- FB_READ(uHandle,fld_type,1)
- fld_type := SUBSTR(fld_type,1,1)
-
- * field length - 16th position
- nSpot := (nLoop*32)+16
- FB_SEEK(uHandle,nSpot,&FB_BEGIN)
- FB_READ(uHandle,fld_len,1)
-
- * field decimal - 17th position
- FB_READ(uHandle,fld_dec,1)
-
- * print the field and continue
- cText := STR(nLoop,5,0)+" "+;
- SUBSTR(fld_name+SPACE(12),1,12)
- DO CASE
- CASE fld_type = "C"
- cText += "Character"
- CASE fld_type = "D"
- cText += "Date "
- CASE fld_type = "L"
- cText += "Logical "
- CASE fld_type = "M"
- cText += "Memo "
- CASE fld_type = "N"
- cText += "Numeric "
- OTHERWISE
- cText += "unknown "
- ENDCASE
- cText += STR(ASC(fld_len),8,0)
- IF fld_type = "N"
- cText += STR(ASC(fld_dec),6,0)
- ENDIF
- IF fld_type = "M"
- * Type of memo
- DO CASE
- CASE cVersion $ "â"
- cText += " DB3"
- CASE cVersion $ "ï"
- cText += " DB4"
- CASE cVersion $ "⌡"
- cText += " Fox"
- ENDCASE
- ENDIF
- cText += cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- ENDIF
- NEXT
- cText := "** Total **"+STR(nRecSize,25,0)+cr_lf
- ELSE
- cText += STR( nRecs, 12, 0 )
- cText += " "+;
- RIGHT("00"+LTRIM(STR(ASC(SUBSTR(cLastUpdate,2,1)),2,0)),2)+"/"+;
- RIGHT("00"+LTRIM(STR(ASC(SUBSTR(cLastUpdate,3,1)),2,0)),2)+"/"+;
- STR(ASC(SUBSTR(cLastUpdate,1,1)),2,0)
- ENDIF
- ELSE
-
- * Number of records in dBASE II header
- FB_SEEK( uHandle, 1, &FB_BEGIN )
- FB_READ( uHandle, nRecs, 2 )
- cText += STR( nRecs, 12, 0 )
-
- * Record size
- FB_SEEK( uHandle, 6, &FB_BEGIN )
- FB_READ( uHandle, nRecSize, 1 )
-
- * dBase II file structure is different...
- IF lStructure
- cText := "Name of database file: "+FIND_FSTR()+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := "Number of records: "+;
- LTRIM(STR( nRecs, 12, 0 ))+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- cText := "Field Field name Type Width Dec"+cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- ELSE
- * Don't know last update for dBase II files
- cText += " " + DTOC( FIND_FDATE() )
- ENDIF
-
- * Figure out the number of fields (max = 32)
- nFields := 0
- FOR nLoop := 1 TO 32
-
- * Position to field start
- nSpot := 8 + ( (nLoop-1) * 16 )
- FB_SEEK(uHandle,nSpot,&FB_BEGIN)
-
- * Read field name
- FB_READ(uHandle,fld_name,10)
-
- * Check if a valid field name
- IF AT( SUBSTR(fld_name,1,1), CHR(13)+CHR(0) ) > 0
- EXIT
- ELSE
- nFields ++
- ENDIF
-
- IF lStructure
- * print field and continue
- cText := STR(nFields,5,0)+" "
- cText += SUBSTR(fld_name+SPACE(12),1,12)
-
- * Gobble up an extra character ...
- FB_READ(uHandle,fld_type,1)
-
- * Read field type
- FB_READ(uHandle,fld_type,1)
- DO CASE
- CASE fld_type = "C"
- cText += "Character"
- CASE fld_type = "D"
- cText += "Date "
- CASE fld_type = "L"
- cText += "Logical "
- CASE fld_type = "M"
- cText += "Memo "
- CASE fld_type = "N"
- cText += "Numeric "
- OTHERWISE
- cText += "unknown "
- ENDCASE
-
- * field length
- FB_READ(uHandle,fld_len,1)
- cText += STR(ASC(fld_len),8,0)
-
- * field decimal (?)
- FB_READ(uHandle,fld_dec,1)
- IF fld_type = "N"
- cText += STR(ASC(fld_dec),6,0)
- ENDIF
- cText += cr_lf
- FB_WRITE(&STD_OUT,cText,LEN(cText))
-
- cText := "** Total **"+STR(nRecSize,25,0)+cr_lf
- ENDIF
-
- NEXT
-
- ENDIF
-
- IF .NOT. lStructure
-
- * File size
- cText += STR( FIND_FSIZE(), 12, 0 )
-
- * Record size
- cText += STR( nRecSize, 8, 0 )
-
- * Number of fields
- cText += STR( nFields, 8, 0 ) + " "
-
- * Does file have memo fields?
- IF cVersion $ "âï⌡"
- cText += "Yes "
- ELSE
- cText += "No "
- ENDIF
-
- * Type of file
- DO CASE
- CASE cVersion $ ""
- cText += "dB2"
- CASE cVersion $ "â"
- cText += "dB3"
- CASE cVersion $ "ï"
- cText += "dB4"
- CASE cVersion $ "⌡"
- cText += "Fox"
- ENDCASE
- IF cCDXbyte = ""
- cText += "+CDX"
- ENDIF
- ENDIF
-
- ELSE
- cText += " ** Unrecognized database type **"
- ENDIF
-
- FB_WRITE(&STD_OUT,cText,LEN(cText))
- FB_WRITE(&STD_OUT,cr_lf,2)
-
- FB_CLOSE(uHandle)
-
- UNTIL .NOT. FIND_NEXT()
-
- QUIT
-
- ENDPRO
-
- *: EOF: DBFDIR.PRG